//不同温度区间显示不同的颜色
const interval0To20 = new gradientColor('#6600FF','#6699FF',10);   //0到20
const interval21To30 = new gradientColor('#6699FF','#FFFF00',10);  //20到30
const interval31To40 = new gradientColor('#FFCC33','#FF6600',10);  //30到40
const interval41To50 = new gradientColor('#FF6600','#FF3300',10);  //40到50
const interval51To100 = new gradientColor('#FF3300','#990033',50);  //50到60

/**
 * 初始化渲染器
 */
export function initRenderer() {
    let renderer = new THREE.WebGLRenderer({
        antialias: true,
    });
    var width = document.getElementById("chart-3d").offsetWidth;
    var height = document.getElementById("chart-3d").offsetHeight;
    renderer.setSize(width, height);
    //设置近乎白色的透明颜色（默认为黑色）
    renderer.setClearColor(0xffffff);
    document.getElementById("chart-3d").append(renderer.domElement);
    renderer.setPixelRatio(2);
    return renderer
}

/**
 * 初始化相机
 * @param {*} initialPosition 
 * @returns 
 */
export function initCamera(initialPosition) {
    var position = (initialPosition !== undefined) ? initialPosition : new THREE.Vector3(-30, 40, 30);

    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
    camera.position.copy(position);
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    return camera;
}

/**
 * 初始化轨迹球
 * @param {*} camera 
 * @param {*} renderer 
 * @returns 
 */
export function initorbitControls(camera, renderer) {
    let orbitControls = new THREE.OrbitControls(
        camera,
        renderer.domElement
    );
    //控制焦点
    // this.orbitControls.target = new THREE.Vector3(0, 0, 0);
    // 使动画循环使用时阻尼或自转 意思是否有惯性
    orbitControls.enableDamping = false;
    //是否可以缩放
    orbitControls.enableZoom = true;
    //是否自动旋转
    orbitControls.autoRotate = true;
    //设置相机距离原点的最进距离
    orbitControls.minDistance = 1000;
    //设置相机距离原点的最远距离
    orbitControls.maxDistance = 2000;
    //是否开启右键拖拽
    orbitControls.enablePan = true;

    return orbitControls;
}

/**
 * 初始化天空盒
 * @param {*} scene 
 */
export function initSky(scene) {
    let materials = [];
    for (var i = 0; i < 6; i++) {
        let texture = new THREE.TextureLoader().load(
            require("../../assets/img/sky-img.png"),
            (load) => { },
            (progress) => { },
            (err) => {
                console.log(err);
            }
        );
        materials.push(
            new THREE.MeshBasicMaterial({
                map: texture,
                side: THREE.BackSide,
            })
        );
    }
    let cube = new THREE.Mesh(
        new THREE.CubeGeometry(9000, 9000, 9000),
        materials
    );
    cube.name = "sky";
    scene.add(cube);
}

/**
 * 初始化特效
 * @param {*} scene 
 * @param {*} camera 
 * @param {*} renderer 
 * @param {需要进行发光处理的mesh对象:包含一二三级告警} meshs 
 * @returns 
 */
export function initComposer(scene, camera, renderer, meshs) {
    let composer = new THREE.EffectComposer(renderer); // 特效组件

    var renderPass = new THREE.RenderPass(scene, camera);
    composer.addPass(renderPass); // 特效渲染

    //一级告警
    var outlinePass = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePass); // 加入高光特效
    outlinePass.pulsePeriod = 3; //数值越大，律动越慢
    outlinePass.visibleEdgeColor.set(0xff0000); // 高光颜色
    outlinePass.hiddenEdgeColor.set(0x000000);// 阴影颜色
    outlinePass.usePatternTexture = false; // 使用纹理覆盖？
    outlinePass.edgeStrength = 10; // 高光边缘强度
    outlinePass.edgeGlow = 1; // 边缘微光强度
    outlinePass.edgeThickness = 1; // 高光厚度
    outlinePass.selectedObjects = meshs.level1Meshs; // 需要高光的obj

    //二级告警
    var outlinePass2 = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePass2); // 加入高光特效
    outlinePass2.pulsePeriod = 2; //数值越大，律动越慢
    outlinePass2.visibleEdgeColor.set(0xff0000); // 高光颜色
    outlinePass2.hiddenEdgeColor.set(0x000000);// 阴影颜色
    outlinePass2.usePatternTexture = false; // 使用纹理覆盖？
    outlinePass2.edgeStrength = 10; // 高光边缘强度
    outlinePass2.edgeGlow = 1; // 边缘微光强度
    outlinePass2.edgeThickness = 2; // 高光厚度
    outlinePass2.selectedObjects = meshs.level2Meshs; // 需要高光的obj

    //三级告警
    var outlinePass3 = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePass3); // 加入高光特效
    outlinePass3.pulsePeriod = 1; //数值越大，律动越慢
    outlinePass3.visibleEdgeColor.set(0xff0000); // 高光颜色
    outlinePass3.hiddenEdgeColor.set(0x000000);// 阴影颜色
    outlinePass3.usePatternTexture = false; // 使用纹理覆盖？
    outlinePass3.edgeStrength = 10; // 高光边缘强度
    outlinePass3.edgeGlow = 1; // 边缘微光强度
    outlinePass3.edgeThickness = 3; // 高光厚度
    outlinePass3.selectedObjects = meshs.level3Meshs; // 需要高光的obj

    //升温告警
    var hartUp = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(hartUp); // 加入高光特效
    hartUp.pulsePeriod = 3; //数值越大，律动越慢
    hartUp.visibleEdgeColor.set("#dfe207"); // 高光颜色
    hartUp.hiddenEdgeColor.set(0x000000);// 阴影颜色
    hartUp.usePatternTexture = false; // 使用纹理覆盖？
    hartUp.edgeStrength = 10; // 高光边缘强度
    hartUp.edgeGlow = 1; // 边缘微光强度
    hartUp.edgeThickness = 3; // 高光厚度
    hartUp.selectedObjects = meshs.hartUp; // 需要高光的obj

    //定温告警
    var constant = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(constant); // 加入高光特效
   constant.pulsePeriod = 3; //数值越大，律动越慢
   constant.visibleEdgeColor.set("#e26407"); // 高光颜色
   constant.hiddenEdgeColor.set(0x000000);// 阴影颜色
   constant.usePatternTexture = false; // 使用纹理覆盖？
   constant.edgeStrength = 10; // 高光边缘强度
   constant.edgeGlow = 1; // 边缘微光强度
   constant.edgeThickness = 3; // 高光厚度
   constant.selectedObjects = meshs.constant; // 需要高光的obj

    //选中的特效
    var outlinePassSelect = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePassSelect); // 加入高光特效
    outlinePassSelect.pulsePeriod = 2; //数值越大，律动越慢
    outlinePassSelect.visibleEdgeColor.set("#bc06f9"); // 高光颜色
    outlinePassSelect.hiddenEdgeColor.set(0x000000);// 阴影颜色
    outlinePassSelect.usePatternTexture = false; // 使用纹理覆盖？
    outlinePassSelect.edgeStrength = 10; // 高光边缘强度
    outlinePassSelect.edgeGlow = 1; // 边缘微光强度
    outlinePassSelect.edgeThickness = 3; // 高光厚度
    outlinePassSelect.selectedObjects = []; // 需要高光的obj

    return { composer, outlinePass, outlinePass2, outlinePass3, hartUp, constant, outlinePassSelect };
}

/**
 * 创建相机动画
 * @param {*} camera 
 * @returns 
 */
export function initTween(camera) {
    let tween = {
        count: { c: 1 },
        obj: Object,
    }
    //x  -1200  200 
    tween.obj = new TWEEN.Tween(tween.count)
        .to({ c: 3 }, 3000)
        .easing(TWEEN.Easing.Sinusoidal.InOut);
    tween.obj.onUpdate(() => {
        if (tween.count.c <= 3) {
            camera.position.z = 3500 - 550 * tween.count.c;
            camera.position.x = - (200 * tween.count.c);
        } else {
            tween.obj.stop();
        }
    });
    tween.obj.start();
    return tween
}

// 获取与射线相交的对象数组
export function getIntersects(event, scene, camera, $) {
    event.preventDefault();
    //div内的canvas
    var width = 0;
    var height = 0;
    if ($("#chart-3d").get(0)) {
        width = parseInt($("#chart-3d").get(0).offsetWidth);
        height = parseInt($("#chart-3d").get(0).offsetHeight);
    }

    // e.target获取的canvas对象
    let obj = event.target;
    let objSet = obj.getBoundingClientRect();

    let x = ((event.clientX - objSet.left) / width) * 2 - 1; // 标准设备横坐标
    let y = -((event.clientY - objSet.top) / height) * 2 + 1; // 标准设备纵坐标

    let standardVector = new THREE.Vector3(x, y, 1); // 标准设备坐标
    //  标准设备坐标转世界坐标
    let worldVector = standardVector.unproject(camera);
    // 射线投射方向单位向量(worldVector坐标减相机位置坐标)
    let ray = worldVector.sub(camera.position).normalize();
    // 创建射线投射器对象
    let rayCaster = new THREE.Raycaster(camera.position, ray);

    // 返回射线选中的对象 第二个参数如果不填 默认是false
    let intersects = rayCaster.intersectObjects(scene.children, true);

    //返回选中的对象
    return intersects;
}

/**
 * 闪动显示网格
 * @param {特效组件} composer
 * @param {场景} scene
 * @param {相机} camera
 * @param {网格数组} meshs 
 * @param {律动频率} frequency 
 */
export function outlineMesh(composer, scene, camera, meshs, frequency) {
    var renderPass = new THREE.RenderPass(scene, camera);
    composer.addPass(renderPass); // 特效渲染

    var outlinePass = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePass); // 加入高光特效

    outlinePass.pulsePeriod = frequency; //数值越大，律动越慢
    outlinePass.visibleEdgeColor.set(0xff0000); // 高光颜色
    outlinePass.hiddenEdgeColor.set(0x000000);// 阴影颜色
    outlinePass.usePatternTexture = false; // 使用纹理覆盖？
    outlinePass.edgeStrength = 10; // 高光边缘强度
    outlinePass.edgeGlow = 1; // 边缘微光强度
    outlinePass.edgeThickness = 1; // 高光厚度

    outlinePass.selectedObjects = meshs; // 需要高光的obj
}

/**
 * 单选选中网格-改变网格材质
 * @param {*} scene 
 * @param {*} currentMesh 
 * @param {*} lastMesh 
 */
export function selectMesh(currentMesh, lastMesh, gradient) {
    if (!currentMesh) {
        return;
    }
    //恢复上一次选中的网格
    if (lastMesh) {
        if (lastMesh.name.includes("channel")) {
            lastMesh.material = currentMesh.material = new THREE.MeshBasicMaterial({
                color: 0x03d7db,
                opacity: 0.8,
                transparent: true
            });

        }
        if (lastMesh.name.includes("passageway")) {
            lastMesh.material = getMaterialbyTemp2(lastMesh.temp,gradient)
        }
    }
    // 改变选中网格材质
    if (currentMesh.name.includes("channel")) {
        currentMesh.material = new THREE.MeshBasicMaterial({
            color: 0x0b0bfa,
            opacity: 0.8,
            transparent: true
        });

    }
    if (currentMesh.name.includes("passageway")) {
        currentMesh.material = new THREE.MeshBasicMaterial({
            color: '#DB2B62',
        });
    }
}
/**
 * 移除网格选中
 * @param {*} mesh 
 * @returns 
 */
export function removeMeshSelect(mesh) {
    if (!mesh) { return }
    if (mesh.name.includes("channel")) {
        mesh.material = new THREE.MeshBasicMaterial({
            color: 0x03d7db,
            opacity: 0.8,
            transparent: true
        });

    }
    if (mesh.name.includes("passageway")) {
        mesh.material = new THREE.MeshBasicMaterial({
            color: 0x2bff2b,
        });

    }
}

/**
 * 根据温度 告警阈值 渲染各个测温点的颜色
 * @param {*} scene 
 * @param {所有测温点的温度数据，已按通道分组} temps 
 * @param {告警阈值配置} tempTV 
 * @param {各个通道类型的数量} aisleInterval 
 */
export function renderTemps(scene, temps, tempTV, aisleInterval,gradient) {

    let nullMaterial = new THREE.MeshBasicMaterial({
        color: "#d1d1e0",
    });

    let normalMaterial = new THREE.MeshBasicMaterial({
        color: 'rgb(100,3,72)',
    });

    let levelOneMaterial = new THREE.MeshBasicMaterial({
        color: "#ff4d4d",
    });

    let levelTwoMaterial = new THREE.MeshBasicMaterial({
        color: "#ff0000",
    });

    let levelThreeMaterial = new THREE.MeshBasicMaterial({
        color: "#cc0000",
    });

    //电池仓的最大区间点
    let warehousePoint = aisleInterval.warehouseNum
    //电池柜的最大区间点
    let cabintPoint = warehousePoint + aisleInterval.cabinetNum;
    //线槽的最大区间点
    let linePoint = cabintPoint + aisleInterval.lineNum;

    let interval = { warehousePoint, cabintPoint, linePoint }

    temps.some((aisleData, aisleNum) => {
        aisleData.some((temp, aisleInde) => {
            //通道号
            let aisle = aisleNum + 1
            //测温点在通道上的索引
            let index = aisleInde + 1

            let mesh = scene.getObjectByName("passageway_" + aisle + "_" + index);
            // getMaterialbyTemp2(temp,colors);
            if (mesh) {
                mesh.temp = temp
    
                mesh.material = getMaterialbyTemp2(temp,gradient)
                // mesh.material = getMaterialbyTemp(temp);

                // mesh.material = new THREE.MeshBasicMaterial({color:colors[temp.toFixed(2)]});
                // //判断是否告警
                // let alarm = jumpAlarm(temp, aisle, tempTV, interval);
                // if (!alarm) {
                //     //为空 标为灰色
                //     mesh.material = nullMaterial
                // } else if (alarm == -1) {

                //     mesh.material = normalMaterial
                //     // mesh.material = new THREE.MeshBasicMaterial({
                //     //     color: gradient[Math.floor(temp/5)],
                //     // });
                //     mesh.material = getMaterialbyTemp(temp);

                // } else if (alarm == 1) {
                //     mesh.material = levelOneMaterial
                // } else if (alarm == 2) {
                //     mesh.material = levelTwoMaterial
                // } else if (alarm == 3) {
                //     mesh.material = levelThreeMaterial
                // }
            }
        })
    })
}

/**
 * 判断是否温度告警
 * @param {测温点的温度} temp 
 * @param {通道号} aisle 
 * @param {告警阈值配置} tempTV 
 * @param {通道的区间} interval 
 * @returns 
 */
function jumpAlarm(temp, aisle, tempTV, interval) {
    //判断是电池仓，充电柜，还是线槽
    if (!temp) {
        //温度为空，直接返回空
        return null;
    }
    let type = aisle <= interval.warehousePoint ? 'warehouse' : aisle <= interval.cabintPoint ? 'cabinet' : 'line';

    //如果是电池仓
    if (type == 'warehouse') {
        return temp < tempTV.warehouse.levelOne ? -1 : temp < tempTV.warehouse.levelTwo ? 1 : temp < tempTV.warehouse.levelThree ? 2 : 3
    }
    //如果是充电机柜
    if (type == 'cabinet') {
        let cabinet = tempTV.cabinet
        return temp < cabinet.levelOne ? -1 : temp < cabinet.levelTwo ? 1 : temp < cabinet.levelThree ? 2 : 3
    }
    //如果是线槽
    if (type == 'line') {
        let line = tempTV.line
        return temp < line.levelOne ? -1 : temp < line.levelTwo ? 1 : temp < line.levelThree ? 2 : 3
    }

}

function getMaterialbyTemp(temp) {
    if(temp<=20){
        return new THREE.MeshBasicMaterial({color:interval0To20[Math.floor(temp/20)]});
    }else if(temp<=30){
        return new THREE.MeshBasicMaterial({color:interval21To30[Math.floor(temp-20)]}); 
    }else if(temp<=40){
        return new THREE.MeshBasicMaterial({color:interval31To40[Math.floor(temp-30)]}); 
    }else if(temp<=50){
        return new THREE.MeshBasicMaterial({color:interval41To50[Math.floor(temp-40)]}); 
    }else if(temp<=100){
        return new THREE.MeshBasicMaterial({color:interval51To100[Math.floor(temp-50)]}); 
    }
}

function getMaterialbyTemp2(temp,gradient) {
    let color = null;
    if(!temp){
        return new THREE.MeshBasicMaterial({
            color: "#d1d1e0",
        });
    }
    let temps = gradient.temps

    if(temp<temps[0]){
        return new THREE.MeshBasicMaterial({
            color: "#3300FF",
            opacity: 0.1
        });
    }
    if(temp>temps[temps.length-1]){
        return new THREE.MeshBasicMaterial({
            color: "#FF0000",
            opacity: 1
        });
    }
    let reIndex = 0;
    for(var index=0;index<temps.length;index++){
        if(temps[index]>temp){
            reIndex = index-1
            break;
        }
    }
    color = gradient.colors[reIndex]
    return new THREE.MeshBasicMaterial({color,opacity:0.5}); 

}
